package com.alpha.service.initial;

import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.mvc.condition.PathPatternsRequestCondition;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import javax.annotation.Nonnull;

/**
 * 服务初始化器
 *
 * @author chenruwan
 * @since 2022-01-01
 */
@Slf4j
@Component
@ConditionalOnClass({WebMvcConfigurer.class})
public class ApplicationInitializer implements ApplicationListener<ContextRefreshedEvent> {
    private final ApplicationContext applicationContext;

    public ApplicationInitializer(@Lazy ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    @Override
    public void onApplicationEvent(@Nonnull ContextRefreshedEvent event) {
        /*
         * OpenFeign 初始化 FeignContext 时会提前触发 ContextRefreshedEvent 事件，
         * 此时有些 Bean 还未创建，会导致 getBean 异常。
         * LoadBalancerClientFactory 也会提前触发 ContextRefreshedEvent 事件。
         */
        if (!event.getApplicationContext().getDisplayName()
                .contains(AnnotationConfigServletWebServerApplicationContext.class.getSimpleName())) {
            return;
        }

        for (String bean : applicationContext.getBeanDefinitionNames()) {
            log.info("definition bean : {} of type {}", bean, applicationContext.getBean(bean).getClass().getName());
        }

        RequestMappingHandlerMapping mappingHandler = applicationContext.getBean(RequestMappingHandlerMapping.class);
        for (RequestMappingInfo mappingInfo : mappingHandler.getHandlerMethods().keySet()) {
            PathPatternsRequestCondition pathPatterns = mappingInfo.getPathPatternsCondition();
            if (pathPatterns != null) {
                log.info("request mapping : {{} {}}]", mappingInfo.getMethodsCondition().getMethods(), pathPatterns);
            }
        }
    }
}
